home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i089: GNU AWK, version 2.11, Part03/16
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 18ccb1bd ddb6cf98 d87e1396 ed05c1c0
-
- Submitted-by: "Arnold D. Robbins" <arnold@unix.cc.emory.edu>
- Posting-number: Volume 22, Issue 89
- Archive-name: gawk2.11/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: ./gawk.texinfo.04 ./missing.d/strtod.c
- # Wrapped by rsalz@litchi.bbn.com on Wed Jun 6 12:24:47 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 3 (of 16)."'
- if test -f './gawk.texinfo.04' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./gawk.texinfo.04'\"
- else
- echo shar: Extracting \"'./gawk.texinfo.04'\" \(49666 characters\)
- sed "s/^X//" >'./gawk.texinfo.04' <<'END_OF_FILE'
- Xoften necessary to insure that it happens where you want it to by
- Xenclosing the items to be concatenated in parentheses. For example, the
- Xfollowing code fragment does not concatenate @code{file} and @code{name}
- Xas you might expect:
- X
- X@example
- Xfile = "file"
- Xname = "name"
- Xprint "something meaningful" > file name
- X@end example
- X
- X@noindent
- XIt is necessary to use the following:
- X
- X@example
- Xprint "something meaningful" > (file name)
- X@end example
- X
- XWe recommend you use parentheses around concatenation in all but the
- Xmost common contexts (such as in the right-hand operand of @samp{=}).
- X
- X@ignore
- X@code{gawk} actually now allows a concatenation on the right hand
- Xside of a @code{>} redirection, but other @code{awk}s don't. So for
- Xnow we won't mention that fact.
- X@end ignore
- X
- X@node Comparison Ops, Boolean Ops, Concatenation, Expressions
- X@section Comparison Expressions
- X@cindex comparison expressions
- X@cindex expressions, comparison
- X@cindex relational operators
- X@cindex operators, relational
- X@cindex regexp operators
- X
- X@dfn{Comparison expressions} compare strings or numbers for
- Xrelationships such as equality. They are written using @dfn{relational
- Xoperators}, which are a superset of those in C. Here is a table of
- Xthem:
- X
- X@table @code
- X@item @var{x} < @var{y}
- XTrue if @var{x} is less than @var{y}.
- X
- X@item @var{x} <= @var{y}
- XTrue if @var{x} is less than or equal to @var{y}.
- X
- X@item @var{x} > @var{y}
- XTrue if @var{x} is greater than @var{y}.
- X
- X@item @var{x} >= @var{y}
- XTrue if @var{x} is greater than or equal to @var{y}.
- X
- X@item @var{x} == @var{y}
- XTrue if @var{x} is equal to @var{y}.
- X
- X@item @var{x} != @var{y}
- XTrue if @var{x} is not equal to @var{y}.
- X
- X@item @var{x} ~ @var{y}
- XTrue if the string @var{x} matches the regexp denoted by @var{y}.
- X
- X@item @var{x} !~ @var{y}
- XTrue if the string @var{x} does not match the regexp denoted by @var{y}.
- X
- X@item @var{subscript} in @var{array}
- XTrue if array @var{array} has an element with the subscript @var{subscript}.
- X@end table
- X
- XComparison expressions have the value 1 if true and 0 if false.
- X
- XThe operands of a relational operator are compared as numbers if they
- Xare both numbers. Otherwise they are converted to, and compared as,
- Xstrings (@pxref{Conversion}). Strings are compared by comparing the
- Xfirst character of each, then the second character of each, and so on.
- XThus, @code{"10"} is less than @code{"9"}.
- X
- XFor example,
- X
- X@example
- X$1 == "foo"
- X@end example
- X
- X@noindent
- Xhas the value of 1, or is true, if the first field of the current input
- Xrecord is precisely @samp{foo}. By contrast,
- X
- X@example
- X$1 ~ /foo/
- X@end example
- X
- X@noindent
- Xhas the value 1 if the first field contains @samp{foo}.
- X
- XThe right hand operand of the @samp{~} and @samp{!~} operators may be
- Xeither a constant regexp (@code{/@dots{}/}), or it may be an ordinary
- Xexpression, in which case the value of the expression as a string is a
- Xdynamic regexp (@pxref{Regexp Usage}).
- X
- X@cindex regexp as expression
- XIn very recent implementations of @code{awk}, a constant regular
- Xexpression in slashes by itself is also an expression. The regexp
- X@code{/@var{regexp}/} is an abbreviation for this comparison expression:
- X
- X@example
- X$0 ~ /@var{regexp}/
- X@end example
- X
- XIn some contexts it may be necessary to write parentheses around the
- Xregexp to avoid confusing the @code{gawk} parser. For example,
- X@code{(/x/ - /y/) > threshold} is not allowed, but @code{((/x/) - (/y/))
- X> threshold} parses properly.
- X
- XOne special place where @code{/foo/} is @emph{not} an abbreviation for
- X@code{$0 ~ /foo/} is when it is the right-hand operand of @samp{~} or
- X@samp{!~}!
- X
- X@node Boolean Ops, Assignment Ops, Comparison Ops, Expressions
- X@section Boolean Expressions
- X@cindex expressions, boolean
- X@cindex boolean expressions
- X@cindex operators, boolean
- X@cindex boolean operators
- X@cindex logical operations
- X@cindex and operator
- X@cindex or operator
- X@cindex not operator
- X
- XA @dfn{boolean expression} is combination of comparison expressions or
- Xmatching expressions, using the @dfn{boolean operators} ``or''
- X(@samp{||}), ``and'' (@samp{&&}), and ``not'' (@samp{!}), along with
- Xparentheses to control nesting. The truth of the boolean expression is
- Xcomputed by combining the truth values of the component expressions.
- X
- XBoolean expressions can be used wherever comparison and matching
- Xexpressions can be used. They can be used in @code{if} and @code{while}
- Xstatements. They have numeric values (1 if true, 0 if false), which
- Xcome into place if the result of the boolean expression is stored in a
- Xvariable, or used in arithmetic.
- X
- XIn addition, every boolean expression is also a valid boolean pattern, so
- Xyou can use it as a pattern to control the execution of rules.
- X
- XHere are descriptions of the three boolean operators, with an example of
- Xeach. It may be instructive to compare these examples with the
- Xanalogous examples of boolean patterns (@pxref{Boolean Patterns}), which
- Xuse the same boolean operators in patterns instead of expressions.
- X
- X@table @code
- X@item @var{boolean1} && @var{boolean2}
- XTrue if both @var{boolean1} and @var{boolean2} are true. For example,
- Xthe following statement prints the current input record if it contains
- Xboth @samp{2400} and @samp{foo}.@refill
- X
- X@example
- Xif ($0 ~ /2400/ && $0 ~ /foo/) print
- X@end example
- X
- XThe subexpression @var{boolean2} is evaluated only if @var{boolean1}
- Xis true. This can make a difference when @var{boolean2} contains
- Xexpressions that have side effects: in the case of @code{$0 ~ /foo/ &&
- X($2 == bar++)}, the variable @code{bar} is not incremented if there is
- Xno @samp{foo} in the record.
- X
- X@item @var{boolean1} || @var{boolean2}
- XTrue if at least one of @var{boolean1} and @var{boolean2} is true.
- XFor example, the following command prints all records in the input
- Xfile @file{BBS-list} that contain @emph{either} @samp{2400} or
- X@samp{foo}, or both.@refill
- X
- X@example
- Xawk '@{ if ($0 ~ /2400/ || $0 ~ /foo/) print @}' BBS-list
- X@end example
- X
- XThe subexpression @var{boolean2} is evaluated only if @var{boolean1}
- Xis false. This can make a difference when @var{boolean2} contains
- Xexpressions that have side effects.
- X
- X@item !@var{boolean}
- XTrue if @var{boolean} is false. For example, the following program prints
- Xall records in the input file @file{BBS-list} that do @emph{not} contain the
- Xstring @samp{foo}.
- X
- X@example
- Xawk '@{ if (! ($0 ~ /foo/)) print @}' BBS-list
- X@end example
- X@end table
- X
- X@node Assignment Ops, Increment Ops, Boolean Ops, Expressions
- X@section Assignment Expressions
- X@cindex assignment operators
- X@cindex operators, assignment
- X@cindex expressions, assignment
- X
- XAn @dfn{assignment} is an expression that stores a new value into a
- Xvariable. For example, let's assign the value 1 to the variable
- X@code{z}:@refill
- X
- X@example
- Xz = 1
- X@end example
- X
- XAfter this expression is executed, the variable @code{z} has the value 1.
- XWhatever old value @code{z} had before the assignment is forgotten.
- X
- XAssignments can store string values also. For example, this would store
- Xthe value @code{"this food is good"} in the variable @code{message}:
- X
- X@example
- Xthing = "food"
- Xpredicate = "good"
- Xmessage = "this " thing " is " predicate
- X@end example
- X
- X@noindent
- X(This also illustrates concatenation of strings.)
- X
- XThe @samp{=} sign is called an @dfn{assignment operator}. It is the
- Xsimplest assignment operator because the value of the right-hand
- Xoperand is stored unchanged.
- X
- X@cindex side effect
- XMost operators (addition, concatenation, and so on) have no effect
- Xexcept to compute a value. If you ignore the value, you might as well
- Xnot use the operator. An assignment operator is different; it does
- Xproduce a value, but even if you ignore the value, the assignment still
- Xmakes itself felt through the alteration of the variable. We call this
- Xa @dfn{side effect}.
- X
- X@cindex lvalue
- XThe left-hand operand of an assignment need not be a variable
- X(@pxref{Variables}); it can also be a field (@pxref{Changing Fields}) or
- Xan array element (@pxref{Arrays}). These are all called @dfn{lvalues},
- Xwhich means they can appear on the left-hand side of an assignment operator.
- XThe right-hand operand may be any expression; it produces the new value
- Xwhich the assignment stores in the specified variable, field or array
- Xelement.
- X
- XIt is important to note that variables do @emph{not} have permanent types.
- XThe type of a variable is simply the type of whatever value it happens
- Xto hold at the moment. In the following program fragment, the variable
- X@code{foo} has a numeric value at first, and a string value later on:
- X
- X@example
- Xfoo = 1
- Xprint foo
- Xfoo = "bar"
- Xprint foo
- X@end example
- X
- X@noindent
- XWhen the second assignment gives @code{foo} a string value, the fact that
- Xit previously had a numeric value is forgotten.
- X
- XAn assignment is an expression, so it has a value: the same value that
- Xis assigned. Thus, @code{z = 1} as an expression has the value 1.
- XOne consequence of this is that you can write multiple assignments together:
- X
- X@example
- Xx = y = z = 0
- X@end example
- X
- X@noindent
- Xstores the value 0 in all three variables. It does this because the
- Xvalue of @code{z = 0}, which is 0, is stored into @code{y}, and then
- Xthe value of @code{y = z = 0}, which is 0, is stored into @code{x}.
- X
- XYou can use an assignment anywhere an expression is called for. For
- Xexample, it is valid to write @code{x != (y = 1)} to set @code{y} to 1
- Xand then test whether @code{x} equals 1. But this style tends to make
- Xprograms hard to read; except in a one-shot program, you should
- Xrewrite it to get rid of such nesting of assignments. This is never very
- Xhard.
- X
- XAside from @samp{=}, there are several other assignment operators that
- Xdo arithmetic with the old value of the variable. For example, the
- Xoperator @samp{+=} computes a new value by adding the right-hand value
- Xto the old value of the variable. Thus, the following assignment adds
- X5 to the value of @code{foo}:
- X
- X@example
- Xfoo += 5
- X@end example
- X
- X@noindent
- XThis is precisely equivalent to the following:
- X
- X@example
- Xfoo = foo + 5
- X@end example
- X
- X@noindent
- XUse whichever one makes the meaning of your program clearer.
- X
- XHere is a table of the arithmetic assignment operators. In each
- Xcase, the right-hand operand is an expression whose value is converted
- Xto a number.
- X
- X@table @code
- X@item @var{lvalue} += @var{increment}
- XAdds @var{increment} to the value of @var{lvalue} to make the new value
- Xof @var{lvalue}.
- X
- X@item @var{lvalue} -= @var{decrement}
- XSubtracts @var{decrement} from the value of @var{lvalue}.
- X
- X@item @var{lvalue} *= @var{coefficient}
- XMultiplies the value of @var{lvalue} by @var{coefficient}.
- X
- X@item @var{lvalue} /= @var{quotient}
- XDivides the value of @var{lvalue} by @var{quotient}.
- X
- X@item @var{lvalue} %= @var{modulus}
- XSets @var{lvalue} to its remainder by @var{modulus}.
- X
- X@item @var{lvalue} ^= @var{power}
- X@itemx @var{lvalue} **= @var{power}
- XRaises @var{lvalue} to the power @var{power}.
- X@end table
- X
- X@node Increment Ops, Conversion, Assignment Ops, Expressions
- X@section Increment Operators
- X
- X@cindex increment operators
- X@cindex operators, increment
- X@dfn{Increment operators} increase or decrease the value of a variable
- Xby 1. You could do the same thing with an assignment operator, so
- Xthe increment operators add no power to the @code{awk} language; but they
- Xare convenient abbreviations for something very common.
- X
- XThe operator to add 1 is written @samp{++}. It can be used to increment
- Xa variable either before or after taking its value.
- X
- XTo pre-increment a variable @var{v}, write @code{++@var{v}}. This adds
- X1 to the value of @var{v} and that new value is also the value of this
- Xexpression. The assignment expression @code{@var{v} += 1} is completely
- Xequivalent.
- X
- XWriting the @samp{++} after the variable specifies post-increment. This
- Xincrements the variable value just the same; the difference is that the
- Xvalue of the increment expression itself is the variable's @emph{old}
- Xvalue. Thus, if @code{foo} has value 4, then the expression @code{foo++}
- Xhas the value 4, but it changes the value of @code{foo} to 5.
- X
- XThe post-increment @code{foo++} is nearly equivalent to writing @code{(foo
- X+= 1) - 1}. It is not perfectly equivalent because all numbers in
- X@code{awk} are floating point: in floating point, @code{foo + 1 - 1} does
- Xnot necessarily equal @code{foo}. But the difference is minute as
- Xlong as you stick to numbers that are fairly small (less than a trillion).
- X
- XAny lvalue can be incremented. Fields and array elements are incremented
- Xjust like variables.
- X
- XThe decrement operator @samp{--} works just like @samp{++} except that
- Xit subtracts 1 instead of adding. Like @samp{++}, it can be used before
- Xthe lvalue to pre-decrement or after it to post-decrement.
- X
- XHere is a summary of increment and decrement expressions.
- X
- X@table @code
- X@item ++@var{lvalue}
- XThis expression increments @var{lvalue} and the new value becomes the
- Xvalue of this expression.
- X
- X@item @var{lvalue}++
- XThis expression causes the contents of @var{lvalue} to be incremented.
- XThe value of the expression is the @emph{old} value of @var{lvalue}.
- X
- X@item --@var{lvalue}
- XLike @code{++@var{lvalue}}, but instead of adding, it subtracts. It
- Xdecrements @var{lvalue} and delivers the value that results.
- X
- X@item @var{lvalue}--
- XLike @code{@var{lvalue}++}, but instead of adding, it subtracts. It
- Xdecrements @var{lvalue}. The value of the expression is the @emph{old}
- Xvalue of @var{lvalue}.
- X@end table
- X
- X@node Conversion, Conditional Exp, Increment Ops, Expressions
- X@section Conversion of Strings and Numbers
- X
- X@cindex conversion of strings and numbers
- XStrings are converted to numbers, and numbers to strings, if the context
- Xof the @code{awk} program demands it. For example, if the value of
- Xeither @code{foo} or @code{bar} in the expression @code{foo + bar}
- Xhappens to be a string, it is converted to a number before the addition
- Xis performed. If numeric values appear in string concatenation, they
- Xare converted to strings. Consider this:@refill
- X
- X@example
- Xtwo = 2; three = 3
- Xprint (two three) + 4
- X@end example
- X
- X@noindent
- XThis eventually prints the (numeric) value 27. The numeric values of
- Xthe variables @code{two} and @code{three} are converted to strings and
- Xconcatenated together, and the resulting string is converted back to the
- Xnumber 23, to which 4 is then added.
- X
- XIf, for some reason, you need to force a number to be converted to a
- Xstring, concatenate the null string with that number. To force a string
- Xto be converted to a number, add zero to that string.
- X
- XStrings are converted to numbers by interpreting them as numerals:
- X@code{"2.5"} converts to 2.5, and @code{"1e3"} converts to 1000.
- XStrings that can't be interpreted as valid numbers are converted to
- Xzero.
- X
- X@vindex OFMT
- XThe exact manner in which numbers are converted into strings is controlled
- Xby the @code{awk} built-in variable @code{OFMT} (@pxref{Built-in Variables}).
- XNumbers are converted using a special
- Xversion of the @code{sprintf} function (@pxref{Built-in}) with @code{OFMT}
- Xas the format specifier.@refill
- X
- X@code{OFMT}'s default value is @code{"%.6g"}, which prints a value with
- Xat least six significant digits. For some applications you will want to
- Xchange it to specify more precision. Double precision on most modern
- Xmachines gives you 16 or 17 decimal digits of precision.
- X
- XStrange results can happen if you set @code{OFMT} to a string that doesn't
- Xtell @code{sprintf} how to format floating point numbers in a useful way.
- XFor example, if you forget the @samp{%} in the format, all numbers will be
- Xconverted to the same constant string.@refill
- X
- X@node Conditional Exp, Function Calls, Conversion, Expressions
- X@section Conditional Expressions
- X@cindex conditional expression
- X@cindex expression, conditional
- X
- XA @dfn{conditional expression} is a special kind of expression with
- Xthree operands. It allows you to use one expression's value to select
- Xone of two other expressions.
- X
- XThe conditional expression looks the same as in the C language:
- X
- X@example
- X@var{selector} ? @var{if-true-exp} : @var{if-false-exp}
- X@end example
- X
- X@noindent
- XThere are three subexpressions. The first, @var{selector}, is always
- Xcomputed first. If it is ``true'' (not zero) then @var{if-true-exp} is
- Xcomputed next and its value becomes the value of the whole expression.
- XOtherwise, @var{if-false-exp} is computed next and its value becomes the
- Xvalue of the whole expression.
- X
- XFor example, this expression produces the absolute value of @code{x}:
- X
- X@example
- Xx > 0 ? x : -x
- X@end example
- X
- XEach time the conditional expression is computed, exactly one of
- X@var{if-true-exp} and @var{if-false-exp} is computed; the other is ignored.
- XThis is important when the expressions contain side effects. For example,
- Xthis conditional expression examines element @code{i} of either array
- X@code{a} or array @code{b}, and increments @code{i}.
- X
- X@example
- Xx == y ? a[i++] : b[i++]
- X@end example
- X
- X@noindent
- XThis is guaranteed to increment @code{i} exactly once, because each time
- Xone or the other of the two increment expressions is executed,
- Xand the other is not.
- X
- X@node Function Calls, Precedence, Conditional Exp, Expressions
- X@section Function Calls
- X@cindex function call
- X@cindex calling a function
- X
- XA @dfn{function} is a name for a particular calculation. Because it has
- Xa name, you can ask for it by name at any point in the program. For
- Xexample, the function @code{sqrt} computes the square root of a number.
- X
- XA fixed set of functions are @dfn{built in}, which means they are
- Xavailable in every @code{awk} program. The @code{sqrt} function is one
- Xof these. @xref{Built-in}, for a list of built-in functions and their
- Xdescriptions. In addition, you can define your own functions in the
- Xprogram for use elsewhere in the same program. @xref{User-defined},
- Xfor how to do this.
- X
- X@cindex arguments in function call
- XThe way to use a function is with a @dfn{function call} expression,
- Xwhich consists of the function name followed by a list of
- X@dfn{arguments} in parentheses. The arguments are expressions which
- Xgive the raw materials for the calculation that the function will do.
- XWhen there is more than one argument, they are separated by commas. If
- Xthere are no arguments, write just @samp{()} after the function name.
- XHere are some examples:
- X
- X@example
- Xsqrt(x**2 + y**2) # @r{One argument}
- Xatan2(y, x) # @r{Two arguments}
- Xrand() # @r{No arguments}
- X@end example
- X
- X@strong{Do not put any space between the function name and the
- Xopen-parenthesis!} A user-defined function name looks just like the name of
- Xa variable, and space would make the expression look like concatenation
- Xof a variable with an expression inside parentheses. Space before the
- Xparenthesis is harmless with built-in functions, but it is best not to get
- Xinto the habit of using space, lest you do likewise for a user-defined
- Xfunction one day by mistake.
- X
- XEach function expects a particular number of arguments. For example, the
- X@code{sqrt} function must be called with a single argument, the number
- Xto take the square root of:
- X
- X@example
- Xsqrt(@var{argument})
- X@end example
- X
- XSome of the built-in functions allow you to omit the final argument.
- XIf you do so, they use a reasonable default. @xref{Built-in},
- Xfor full details. If arguments are omitted in calls to user-defined
- Xfunctions, then those arguments are treated as local variables,
- Xinitialized to the null string (@pxref{User-defined}).
- X
- XLike every other expression, the function call has a value, which is
- Xcomputed by the function based on the arguments you give it. In this
- Xexample, the value of @code{sqrt(@var{argument})} is the square root of the
- Xargument. A function can also have side effects, such as assigning the
- Xvalues of certain variables or doing I/O.
- X
- XHere is a command to read numbers, one number per line, and print the
- Xsquare root of each one:
- X
- X@example
- Xawk '@{ print "The square root of", $1, "is", sqrt($1) @}'
- X@end example
- X
- X@node Precedence,, Function Calls, Expressions
- X@section Operator Precedence: How Operators Nest
- X@cindex precedence
- X@cindex operator precedence
- X
- X@dfn{Operator precedence} determines how operators are grouped, when
- Xdifferent operators appear close by in one expression. For example,
- X@samp{*} has higher precedence than @samp{+}; thus, @code{a + b * c}
- Xmeans to multiply @code{b} and @code{c}, and then add @code{a} to the
- Xproduct.
- X
- XYou can overrule the precedence of the operators by writing parentheses
- Xyourself. You can think of the precedence rules as saying where the
- Xparentheses are assumed if you do not write parentheses yourself. In
- Xfact, it is wise always to use parentheses whenever you have an unusual
- Xcombination of operators, because other people who read the program may
- Xnot remember what the precedence is in this case. You might forget,
- Xtoo; then you could make a mistake. Explicit parentheses will prevent
- Xany such mistake.
- X
- XWhen operators of equal precedence are used together, the leftmost
- Xoperator groups first, except for the assignment, conditional and
- Xand exponentiation operators, which group in the opposite order.
- XThus, @code{a - b + c} groups as @code{(a - b) + c};
- X@code{a = b = c} groups as @code{a = (b = c)}.
- X
- XThe precedence of prefix unary operators does not matter as long as only
- Xunary operators are involved, because there is only one way to parse
- Xthem---innermost first. Thus, @code{$++i} means @code{$(++i)} and
- X@code{++$x} means @code{++($x)}. However, when another operator follows
- Xthe operand, then the precedence of the unary operators can matter.
- XThus, @code{$x**2} means @code{($x)**2}, but @code{-x**2} means
- X@code{-(x**2)}, because @samp{-} has lower precedence than @samp{**}
- Xwhile @samp{$} has higher precedence.
- X
- XHere is a table of the operators of @code{awk}, in order of increasing
- Xprecedence:
- X
- X@table @asis
- X@item assignment
- X@samp{=}, @samp{+=}, @samp{-=}, @samp{*=}, @samp{/=}, @samp{%=},
- X@samp{^=}, @samp{**=}. These operators group right-to-left.
- X
- X@item conditional
- X@samp{?:}. These operators group right-to-left.
- X
- X@item logical ``or''.
- X@samp{||}.
- X
- X@item logical ``and''.
- X@samp{&&}.
- X
- X@item array membership
- X@code{in}.
- X
- X@item matching
- X@samp{~}, @samp{!~}.
- X
- X@item relational, and redirection
- XThe relational operators and the redirections have the same precedence
- Xlevel. Characters such as @samp{>} serve both as relationals and as
- Xredirections; the context distinguishes between the two meanings.
- X
- XThe relational operators are @samp{<}, @samp{<=}, @samp{==}, @samp{!=},
- X@samp{>=} and @samp{>}.
- X
- XThe I/O redirection operators are @samp{<}, @samp{>}, @samp{>>} and
- X@samp{|}.
- X
- XNote that I/O redirection operators in @code{print} and @code{printf}
- Xstatements belong to the statement level, not to expressions. The
- Xredirection does not produce an expression which could be the operand of
- Xanother operator. As a result, it does not make sense to use a
- Xredirection operator near another operator of lower precedence, without
- Xparentheses. Such combinations, for example @samp{print foo > a ? b :
- Xc}, result in syntax errors.
- X
- X@item concatentation
- XNo special token is used to indicate concatenation.
- XThe operands are simply written side by side.
- X@c This is supposedly being fixed
- X@ignore
- XConcatenation has the same precedence as relational and redirection
- Xoperators. These operators nest left to right. Thus, @code{4 5 > 6}
- Xconcatenates first, yielding 1, while @code{6 < 4 5} compares first, and
- Xyields @code{"05"}.
- X@end ignore
- X
- X@item add, subtract
- X@samp{+}, @samp{-}.
- X
- X@item multiply, divide, mod
- X@samp{*}, @samp{/}, @samp{%}.
- X
- X@item unary plus, minus, ``not''
- X@samp{+}, @samp{-}, @samp{!}.
- X
- X@item exponentiation
- X@samp{^}, @samp{**}. These operators group right-to-left.
- X
- X@item increment, decrement
- X@samp{++}, @samp{--}.
- X
- X@item field
- X@samp{$}.
- X@end table
- X
- X@node Statements, Arrays, Expressions, Top
- X@chapter Actions: Control Statements
- X@cindex control statement
- X
- X@dfn{Control statements} such as @code{if}, @code{while}, and so on
- Xcontrol the flow of execution in @code{awk} programs. Most of the
- Xcontrol statements in @code{awk} are patterned on similar statements in
- XC.
- X
- XAll the control statements start with special keywords such as @code{if}
- Xand @code{while}, to distinguish them from simple expressions.
- X
- XMany control statements contain other statements; for example, the
- X@code{if} statement contains another statement which may or may not be
- Xexecuted. The contained statement is called the @dfn{body}. If you
- Xwant to include more than one statement in the body, group them into a
- Xsingle compound statement with curly braces, separating them with
- Xnewlines or semicolons.
- X
- X@menu
- X* If Statement:: Conditionally execute some @code{awk} statements.
- X
- X* While Statement:: Loop until some condition is satisfied.
- X
- X* Do Statement:: Do specified action while looping until some
- X condition is satisfied.
- X
- X* For Statement:: Another looping statement, that provides
- X initialization and increment clauses.
- X
- X* Break Statement:: Immediately exit the innermost enclosing loop.
- X
- X* Continue Statement:: Skip to the end of the innermost enclosing loop.
- X
- X* Next Statement:: Stop processing the current input record.
- X
- X* Exit Statement:: Stop execution of @code{awk}.
- X@end menu
- X
- X@node If Statement, While Statement, Statements, Statements
- X@section The @code{if} Statement
- X
- X@cindex @code{if} statement
- XThe @code{if}-@code{else} statement is @code{awk}'s decision-making
- Xstatement. It looks like this:@refill
- X
- X@example
- Xif (@var{condition}) @var{then-body} @r{[}else @var{else-body}@r{]}
- X@end example
- X
- X@noindent
- XHere @var{condition} is an expression that controls what the rest of the
- Xstatement will do. If @var{condition} is true, @var{then-body} is
- Xexecuted; otherwise, @var{else-body} is executed (assuming that the
- X@code{else} clause is present). The @code{else} part of the statement is
- Xoptional. The condition is considered false if its value is zero or
- Xthe null string, true otherwise.@refill
- X
- XHere is an example:
- X
- X@example
- Xif (x % 2 == 0)
- X print "x is even"
- Xelse
- X print "x is odd"
- X@end example
- X
- XIn this example, if the expression @code{x % 2 == 0} is true (that is,
- Xthe value of @code{x} is divisible by 2), then the first @code{print}
- Xstatement is executed, otherwise the second @code{print} statement is
- Xperformed.@refill
- X
- XIf the @code{else} appears on the same line as @var{then-body}, and
- X@var{then-body} is not a compound statement (i.e., not surrounded by
- Xcurly braces), then a semicolon must separate @var{then-body} from
- X@code{else}. To illustrate this, let's rewrite the previous example:
- X
- X@group
- X@example
- Xawk '@{ if (x % 2 == 0) print "x is even"; else
- X print "x is odd" @}'
- X@end example
- X@end group
- X
- X@noindent
- XIf you forget the @samp{;}, @code{awk} won't be able to parse the
- Xstatement, and you will get a syntax error.
- X
- XWe would not actually write this example this way, because a human
- Xreader might fail to see the @code{else} if it were not the first thing
- Xon its line.
- X
- X@node While Statement, Do Statement, If Statement, Statements
- X@section The @code{while} Statement
- X@cindex @code{while} statement
- X@cindex loop
- X@cindex body of a loop
- X
- XIn programming, a @dfn{loop} means a part of a program that is (or at least can
- Xbe) executed two or more times in succession.
- X
- XThe @code{while} statement is the simplest looping statement in
- X@code{awk}. It repeatedly executes a statement as long as a condition is
- Xtrue. It looks like this:
- X
- X@example
- Xwhile (@var{condition})
- X @var{body}
- X@end example
- X
- X@noindent
- XHere @var{body} is a statement that we call the @dfn{body} of the loop,
- Xand @var{condition} is an expression that controls how long the loop
- Xkeeps running.
- X
- XThe first thing the @code{while} statement does is test @var{condition}.
- XIf @var{condition} is true, it executes the statement @var{body}.
- X(Truth, as usual in @code{awk}, means that the value of @var{condition}
- Xis not zero and not a null string.) After @var{body} has been executed,
- X@var{condition} is tested again, and if it is still true, @var{body} is
- Xexecuted again. This process repeats until @var{condition} is no longer
- Xtrue. If @var{condition} is initially false, the body of the loop is
- Xnever executed.@refill
- X
- XThis example prints the first three fields of each record, one per line.
- X
- X@example
- Xawk '@{ i = 1
- X while (i <= 3) @{
- X print $i
- X i++
- X @}
- X@}'
- X@end example
- X
- X@noindent
- XHere the body of the loop is a compound statement enclosed in braces,
- Xcontaining two statements.
- X
- XThe loop works like this: first, the value of @code{i} is set to 1.
- XThen, the @code{while} tests whether @code{i} is less than or equal to
- Xthree. This is the case when @code{i} equals one, so the @code{i}-th
- Xfield is printed. Then the @code{i++} increments the value of @code{i}
- Xand the loop repeats. The loop terminates when @code{i} reaches 4.
- X
- XAs you can see, a newline is not required between the condition and the
- Xbody; but using one makes the program clearer unless the body is a
- Xcompound statement or is very simple. The newline after the open-brace
- Xthat begins the compound statement is not required either, but the
- Xprogram would be hard to read without it.
- X
- X@node Do Statement, For Statement, While Statement, Statements
- X@section The @code{do}-@code{while} Statement
- X
- XThe @code{do} loop is a variation of the @code{while} looping statement.
- XThe @code{do} loop executes the @var{body} once, then repeats @var{body}
- Xas long as @var{condition} is true. It looks like this:
- X
- X@group
- X@example
- Xdo
- X @var{body}
- Xwhile (@var{condition})
- X@end example
- X@end group
- X
- XEven if @var{condition} is false at the start, @var{body} is executed at
- Xleast once (and only once, unless executing @var{body} makes
- X@var{condition} true). Contrast this with the corresponding
- X@code{while} statement:
- X
- X@example
- Xwhile (@var{condition})
- X @var{body}
- X@end example
- X
- X@noindent
- XThis statement does not execute @var{body} even once if @var{condition}
- Xis false to begin with.
- X
- XHere is an example of a @code{do} statement:
- X
- X@example
- Xawk '@{ i = 1
- X do @{
- X print $0
- X i++
- X @} while (i <= 10)
- X@}'
- X@end example
- X
- X@noindent
- Xprints each input record ten times. It isn't a very realistic example,
- Xsince in this case an ordinary @code{while} would do just as well. But
- Xthis reflects actual experience; there is only occasionally a real use
- Xfor a @code{do} statement.@refill
- X
- X@node For Statement, Break Statement, Do Statement, Statements
- X@section The @code{for} Statement
- X@cindex @code{for} statement
- X
- XThe @code{for} statement makes it more convenient to count iterations of a
- Xloop. The general form of the @code{for} statement looks like this:@refill
- X
- X@example
- Xfor (@var{initialization}; @var{condition}; @var{increment})
- X @var{body}
- X@end example
- X
- X@noindent
- XThis statement starts by executing @var{initialization}. Then, as long
- Xas @var{condition} is true, it repeatedly executes @var{body} and then
- X@var{increment}. Typically @var{initialization} sets a variable to
- Xeither zero or one, @var{increment} adds 1 to it, and @var{condition}
- Xcompares it against the desired number of iterations.
- X
- XHere is an example of a @code{for} statement:
- X
- X@example
- Xawk '@{ for (i = 1; i <= 3; i++)
- X print $i
- X@}'
- X@end example
- X
- X@noindent
- XThis prints the first three fields of each input record, one field per
- Xline.
- X
- XIn the @code{for} statement, @var{body} stands for any statement, but
- X@var{initialization}, @var{condition} and @var{increment} are just
- Xexpressions. You cannot set more than one variable in the
- X@var{initialization} part unless you use a multiple assignment statement
- Xsuch as @code{x = y = 0}, which is possible only if all the initial values
- Xare equal. (But you can initialize additional variables by writing
- Xtheir assignments as separate statements preceding the @code{for} loop.)
- X
- XThe same is true of the @var{increment} part; to increment additional
- Xvariables, you must write separate statements at the end of the loop.
- XThe C compound expression, using C's comma operator, would be useful in
- Xthis context, but it is not supported in @code{awk}.
- X
- XMost often, @var{increment} is an increment expression, as in the
- Xexample above. But this is not required; it can be any expression
- Xwhatever. For example, this statement prints all the powers of 2
- Xbetween 1 and 100:
- X
- X@example
- Xfor (i = 1; i <= 100; i *= 2)
- X print i
- X@end example
- X
- XAny of the three expressions in the parentheses following @code{for} may
- Xbe omitted if there is nothing to be done there. Thus, @w{@samp{for (;x
- X> 0;)}} is equivalent to @w{@samp{while (x > 0)}}. If the
- X@var{condition} is omitted, it is treated as @var{true}, effectively
- Xyielding an infinite loop.@refill
- X
- XIn most cases, a @code{for} loop is an abbreviation for a @code{while}
- Xloop, as shown here:
- X
- X@example
- X@var{initialization}
- Xwhile (@var{condition}) @{
- X @var{body}
- X @var{increment}
- X@}
- X@end example
- X
- X@noindent
- XThe only exception is when the @code{continue} statement
- X(@pxref{Continue Statement}) is used inside the loop; changing a
- X@code{for} statement to a @code{while} statement in this way can change
- Xthe effect of the @code{continue} statement inside the loop.
- X
- XThere is an alternate version of the @code{for} loop, for iterating over
- Xall the indices of an array:
- X
- X@example
- Xfor (i in array)
- X @var{do something with} array[i]
- X@end example
- X
- X@noindent
- X@xref{Arrays}, for more information on this version of the @code{for} loop.
- X
- XThe @code{awk} language has a @code{for} statement in addition to a
- X@code{while} statement because often a @code{for} loop is both less work to
- Xtype and more natural to think of. Counting the number of iterations is
- Xvery common in loops. It can be easier to think of this counting as part
- Xof looping rather than as something to do inside the loop.
- X
- XThe next section has more complicated examples of @code{for} loops.
- X
- X@node Break Statement, Continue Statement, For Statement, Statements
- X@section The @code{break} Statement
- X@cindex @code{break} statement
- X@cindex loops, exiting
- X
- XThe @code{break} statement jumps out of the innermost @code{for},
- X@code{while}, or @code{do}-@code{while} loop that encloses it. The
- Xfollowing example finds the smallest divisor of any integer, and also
- Xidentifies prime numbers:@refill
- X
- X@example
- Xawk '# find smallest divisor of num
- X @{ num = $1
- X for (div = 2; div*div <= num; div++)
- X if (num % div == 0)
- X break
- X if (num % div == 0)
- X printf "Smallest divisor of %d is %d\n", num, div
- X else
- X printf "%d is prime\n", num @}'
- X@end example
- X
- XWhen the remainder is zero in the first @code{if} statement, @code{awk}
- Ximmediately @dfn{breaks out} of the containing @code{for} loop. This means
- Xthat @code{awk} proceeds immediately to the statement following the loop
- Xand continues processing. (This is very different from the @code{exit}
- Xstatement (@pxref{Exit Statement}) which stops the entire @code{awk}
- Xprogram.)@refill
- X
- XHere is another program equivalent to the previous one. It illustrates how
- Xthe @var{condition} of a @code{for} or @code{while} could just as well be
- Xreplaced with a @code{break} inside an @code{if}:
- X
- X@example
- Xawk '# find smallest divisor of num
- X @{ num = $1
- X for (div = 2; ; div++) @{
- X if (num % div == 0) @{
- X printf "Smallest divisor of %d is %d\n", num, div
- X break
- X @}
- X if (div*div > num) @{
- X printf "%d is prime\n", num
- X break
- X @}
- X @}
- X@}'
- X@end example
- X
- X@node Continue Statement, Next Statement, Break Statement, Statements
- X@section The @code{continue} Statement
- X
- X@cindex @code{continue} statement
- XThe @code{continue} statement, like @code{break}, is used only inside
- X@code{for}, @code{while}, and @code{do}-@code{while} loops. It skips
- Xover the rest of the loop body, causing the next cycle around the loop
- Xto begin immediately. Contrast this with @code{break}, which jumps out
- Xof the loop altogether. Here is an example:@refill
- X
- X@example
- X# print names that don't contain the string "ignore"
- X
- X# first, save the text of each line
- X@{ names[NR] = $0 @}
- X
- X# print what we're interested in
- XEND @{
- X for (x in names) @{
- X if (names[x] ~ /ignore/)
- X continue
- X print names[x]
- X @}
- X@}
- X@end example
- X
- XIf one of the input records contains the string @samp{ignore}, this
- Xexample skips the print statement for that record, and continues back to
- Xthe first statement in the loop.
- X
- XThis isn't a practical example of @code{continue}, since it would be
- Xjust as easy to write the loop like this:
- X
- X@example
- Xfor (x in names)
- X if (names[x] !~ /ignore/)
- X print names[x]
- X@end example
- X
- XThe @code{continue} statement in a @code{for} loop directs @code{awk} to
- Xskip the rest of the body of the loop, and resume execution with the
- Xincrement-expression of the @code{for} statement. The following program
- Xillustrates this fact:@refill
- X
- X@example
- Xawk 'BEGIN @{
- X for (x = 0; x <= 20; x++) @{
- X if (x == 5)
- X continue
- X printf ("%d ", x)
- X @}
- X print ""
- X@}'
- X@end example
- X
- X@noindent
- XThis program prints all the numbers from 0 to 20, except for 5, for
- Xwhich the @code{printf} is skipped. Since the increment @code{x++}
- Xis not skipped, @code{x} does not remain stuck at 5. Contrast the
- X@code{for} loop above with the @code{while} loop:
- X
- X@example
- Xawk 'BEGIN @{
- X x = 0
- X while (x <= 20) @{
- X if (x == 5)
- X continue
- X printf ("%d ", x)
- X x++
- X @}
- X print ""
- X@}'
- X@end example
- X
- X@noindent
- XThis program loops forever once @code{x} gets to 5.
- X
- X@node Next Statement, Exit Statement, Continue Statement, Statements
- X@section The @code{next} Statement
- X@cindex @code{next} statement
- X
- XThe @code{next} statement forces @code{awk} to immediately stop processing
- Xthe current record and go on to the next record. This means that no
- Xfurther rules are executed for the current record. The rest of the
- Xcurrent rule's action is not executed either.
- X
- XContrast this with the effect of the @code{getline} function
- X(@pxref{Getline}). That too causes @code{awk} to read the next record
- Ximmediately, but it does not alter the flow of control in any way. So
- Xthe rest of the current action executes with a new input record.
- X
- XAt the grossest level, @code{awk} program execution is a loop that reads
- Xan input record and then tests each rule's pattern against it. If you
- Xthink of this loop as a @code{for} statement whose body contains the
- Xrules, then the @code{next} statement is analogous to a @code{continue}
- Xstatement: it skips to the end of the body of this implicit loop, and
- Xexecutes the increment (which reads another record).
- X
- XFor example, if your @code{awk} program works only on records with four
- Xfields, and you don't want it to fail when given bad input, you might
- Xuse this rule near the beginning of the program:
- X
- X@example
- XNF != 4 @{
- X printf("line %d skipped: doesn't have 4 fields", FNR) > "/dev/stderr"
- X next
- X@}
- X@end example
- X
- X@noindent
- Xso that the following rules will not see the bad record. The error
- Xmessage is redirected to the standard error output stream, as error
- Xmessages should be. @xref{Special Files}.
- X
- XThe @code{next} statement is not allowed in a @code{BEGIN} or @code{END}
- Xrule.
- X
- X@node Exit Statement, , Next Statement, Statements
- X@section The @code{exit} Statement
- X
- X@cindex @code{exit} statement
- XThe @code{exit} statement causes @code{awk} to immediately stop
- Xexecuting the current rule and to stop processing input; any remaining input
- Xis ignored.@refill
- X
- XIf an @code{exit} statement is executed from a @code{BEGIN} rule the
- Xprogram stops processing everything immediately. No input records are
- Xread. However, if an @code{END} rule is present, it is executed
- X(@pxref{BEGIN/END}).
- X
- XIf @code{exit} is used as part of an @code{END} rule, it causes
- Xthe program to stop immediately.
- X
- XAn @code{exit} statement that is part an ordinary rule (that is, not part
- Xof a @code{BEGIN} or @code{END} rule) stops the execution of any further
- Xautomatic rules, but the @code{END} rule is executed if there is one.
- XIf you don't want the @code{END} rule to do its job in this case, you
- Xcan set a variable to nonzero before the @code{exit} statement, and check
- Xthat variable in the @code{END} rule.
- X
- XIf an argument is supplied to @code{exit}, its value is used as the exit
- Xstatus code for the @code{awk} process. If no argument is supplied,
- X@code{exit} returns status zero (success).@refill
- X
- XFor example, let's say you've discovered an error condition you really
- Xdon't know how to handle. Conventionally, programs report this by
- Xexiting with a nonzero status. Your @code{awk} program can do this
- Xusing an @code{exit} statement with a nonzero argument. Here's an
- Xexample of this:@refill
- X
- X@example
- XBEGIN @{
- X if (("date" | getline date_now) < 0) @{
- X print "Can't get system date" > "/dev/stderr"
- X exit 4
- X @}
- X@}
- X@end example
- X
- X@node Arrays, Built-in, Statements, Top
- X@chapter Arrays in @code{awk}
- X
- XAn @dfn{array} is a table of various values, called @dfn{elements}. The
- Xelements of an array are distinguished by their @dfn{indices}. Indices
- Xmay be either numbers or strings. Each array has a name, which looks
- Xlike a variable name, but must not be in use as a variable name in the
- Xsame @code{awk} program.
- X
- X@menu
- X* Intro: Array Intro. Basic facts about arrays in @code{awk}.
- X* Reference to Elements:: How to examine one element of an array.
- X* Assigning Elements:: How to change an element of an array.
- X* Example: Array Example. Sample program explained.
- X
- X* Scanning an Array:: A variation of the @code{for} statement. It loops
- X through the indices of an array's existing elements.
- X
- X* Delete:: The @code{delete} statement removes an element from an array.
- X
- X* Multi-dimensional:: Emulating multi-dimensional arrays in @code{awk}.
- X* Multi-scanning:: Scanning multi-dimensional arrays.
- X@end menu
- X
- X@node Array Intro, Reference to Elements, Arrays, Arrays
- X@section Introduction to Arrays
- X
- X@cindex arrays
- XThe @code{awk} language has one-dimensional @dfn{arrays} for storing groups
- Xof related strings or numbers.
- X
- XEvery @code{awk} array must have a name. Array names have the same
- Xsyntax as variable names; any valid variable name would also be a valid
- Xarray name. But you cannot use one name in both ways (as an array and
- Xas a variable) in one @code{awk} program.
- X
- XArrays in @code{awk} superficially resemble arrays in other programming
- Xlanguages; but there are fundamental differences. In @code{awk}, you
- Xdon't need to specify the size of an array before you start to use it.
- XWhat's more, in @code{awk} any number or even a string may be used as an
- Xarray index.
- X
- XIn most other languages, you have to @dfn{declare} an array and specify
- Xhow many elements or components it has. In such languages, the
- Xdeclaration causes a contiguous block of memory to be allocated for that
- Xmany elements. An index in the array must be a positive integer; for
- Xexample, the index 0 specifies the first element in the array, which is
- Xactually stored at the beginning of the block of memory. Index 1
- Xspecifies the second element, which is stored in memory right after the
- Xfirst element, and so on. It is impossible to add more elements to the
- Xarray, because it has room for only as many elements as you declared.
- X
- XA contiguous array of four elements might look like this, conceptually,
- Xif the element values are 8, @code{"foo"}, @code{""} and 30:@refill
- X
- X@example
- X+---------+---------+--------+---------+
- X| 8 | "foo" | "" | 30 | @r{value}
- X+---------+---------+--------+---------+
- X 0 1 2 3 @r{index}
- X@end example
- X
- X@noindent
- XOnly the values are stored; the indices are implicit from the order of
- Xthe values. 8 is the value at index 0, because 8 appears in the
- Xposition with 0 elements before it.
- X
- X@cindex arrays, definition of
- X@cindex associative arrays
- XArrays in @code{awk} are different: they are @dfn{associative}. This means
- Xthat each array is a collection of pairs: an index, and its corresponding
- Xarray element value:
- X
- X@example
- X@r{Element} 4 @r{Value} 30
- X@r{Element} 2 @r{Value} "foo"
- X@r{Element} 1 @r{Value} 8
- X@r{Element} 3 @r{Value} ""
- X@end example
- X
- X@noindent
- XWe have shown the pairs in jumbled order because their order doesn't
- Xmean anything.
- X
- XOne advantage of an associative array is that new pairs can be added
- Xat any time. For example, suppose we add to that array a tenth element
- Xwhose value is @w{@code{"number ten"}}. The result is this:
- X
- X@example
- X@r{Element} 10 @r{Value} "number ten"
- X@r{Element} 4 @r{Value} 30
- X@r{Element} 2 @r{Value} "foo"
- X@r{Element} 1 @r{Value} 8
- X@r{Element} 3 @r{Value} ""
- X@end example
- X
- X@noindent
- XNow the array is @dfn{sparse} (i.e., some indices are missing): it has
- Xelements 4 and 10, but doesn't have elements 5, 6, 7, 8, or 9.@refill
- X
- XAnother consequence of associative arrays is that the indices don't
- Xhave to be positive integers. Any number, or even a string, can be
- Xan index. For example, here is an array which translates words from
- XEnglish into French:
- X
- X@example
- X@r{Element} "dog" @r{Value} "chien"
- X@r{Element} "cat" @r{Value} "chat"
- X@r{Element} "one" @r{Value} "un"
- X@r{Element} 1 @r{Value} "un"
- X@end example
- X
- X@noindent
- XHere we decided to translate the number 1 in both spelled-out and
- Xnumeric form---thus illustrating that a single array can have both
- Xnumbers and strings as indices.
- X
- XWhen @code{awk} creates an array for you, e.g., with the @code{split}
- Xbuilt-in function (@pxref{String Functions}), that array's indices
- Xare consecutive integers starting at 1.
- X
- X@node Reference to Elements, Assigning Elements, Array Intro, Arrays
- X@section Referring to an Array Element
- X@cindex array reference
- X@cindex element of array
- X@cindex reference to array
- X
- XThe principal way of using an array is to refer to one of its elements.
- XAn array reference is an expression which looks like this:
- X
- X@example
- X@var{array}[@var{index}]
- X@end example
- X
- X@noindent
- XHere @var{array} is the name of an array. The expression @var{index} is
- Xthe index of the element of the array that you want.
- X
- XThe value of the array reference is the current value of that array
- Xelement. For example, @code{foo[4.3]} is an expression for the element
- Xof array @code{foo} at index 4.3.
- X
- XIf you refer to an array element that has no recorded value, the value
- Xof the reference is @code{""}, the null string. This includes elements
- Xto which you have not assigned any value, and elements that have been
- Xdeleted (@pxref{Delete}). Such a reference automatically creates that
- Xarray element, with the null string as its value. (In some cases,
- Xthis is unfortunate, because it might waste memory inside @code{awk}).
- X
- X@cindex arrays, determining presence of elements
- XYou can find out if an element exists in an array at a certain index with
- Xthe expression:
- X
- X@example
- X@var{index} in @var{array}
- X@end example
- X
- X@noindent
- XThis expression tests whether or not the particular index exists,
- Xwithout the side effect of creating that element if it is not present.
- XThe expression has the value 1 (true) if @code{@var{array}[@var{index}]}
- Xexists, and 0 (false) if it does not exist.@refill
- X
- XFor example, to test whether the array @code{frequencies} contains the
- Xindex @code{"2"}, you could write this statement:@refill
- X
- X@example
- Xif ("2" in frequencies) print "Subscript \"2\" is present."
- X@end example
- X
- XNote that this is @emph{not} a test of whether or not the array
- X@code{frequencies} contains an element whose @emph{value} is @code{"2"}.
- X(There is no way to do that except to scan all the elements.) Also, this
- X@emph{does not} create @code{frequencies["2"]}, while the following
- X(incorrect) alternative would do so:@refill
- X
- X@example
- Xif (frequencies["2"] != "") print "Subscript \"2\" is present."
- X@end example
- X
- X@node Assigning Elements, Array Example, Reference to Elements, Arrays
- X@section Assigning Array Elements
- X@cindex array assignment
- X@cindex element assignment
- X
- XArray elements are lvalues: they can be assigned values just like
- X@code{awk} variables:
- X
- X@example
- X@var{array}[@var{subscript}] = @var{value}
- X@end example
- X
- X@noindent
- XHere @var{array} is the name of your array. The expression
- X@var{subscript} is the index of the element of the array that you want
- Xto assign a value. The expression @var{value} is the value you are
- Xassigning to that element of the array.@refill
- X
- X@node Array Example, Scanning an Array, Assigning Elements, Arrays
- X@section Basic Example of an Array
- X
- XThe following program takes a list of lines, each beginning with a line
- Xnumber, and prints them out in order of line number. The line numbers are
- Xnot in order, however, when they are first read: they are scrambled. This
- Xprogram sorts the lines by making an array using the line numbers as
- Xsubscripts. It then prints out the lines in sorted order of their numbers.
- XIt is a very simple program, and gets confused if it encounters repeated
- Xnumbers, gaps, or lines that don't begin with a number.@refill
- X
- X@example
- X@{
- X if ($1 > max)
- X max = $1
- X arr[$1] = $0
- X@}
- X
- XEND @{
- X for (x = 1; x <= max; x++)
- X print arr[x]
- X@}
- X@end example
- X
- X@ignore
- XThe first rule just initializes the variable @code{max}. (This is not
- Xstrictly necessary, since an uninitialized variable has the null string
- Xas its value, and the null string is effectively zero when used in
- Xa context where a number is required.)
- X@end ignore
- X
- XThe first rule keeps track of the largest line number seen so far;
- Xit also stores each line into the array @code{arr}, at an index that
- Xis the line's number.
- X
- XThe second rule runs after all the input has been read, to print out
- Xall the lines.
- X
- XWhen this program is run with the following input:
- X
- X@example
- X5 I am the Five man
- X2 Who are you? The new number two!
- X4 . . . And four on the floor
- X1 Who is number one?
- X3 I three you.
- X@end example
- X
- X@noindent
- Xits output is this:
- X
- X@example
- X1 Who is number one?
- X2 Who are you? The new number two!
- X3 I three you.
- X4 . . . And four on the floor
- X5 I am the Five man
- X@end example
- X
- END_OF_FILE
- if test 49666 -ne `wc -c <'./gawk.texinfo.04'`; then
- echo shar: \"'./gawk.texinfo.04'\" unpacked with wrong size!
- fi
- # end of './gawk.texinfo.04'
- fi
- if test -f './missing.d/strtod.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./missing.d/strtod.c'\"
- else
- echo shar: Extracting \"'./missing.d/strtod.c'\" \(2023 characters\)
- sed "s/^X//" >'./missing.d/strtod.c' <<'END_OF_FILE'
- X/*
- X * strtod.c
- X *
- X * Stupid version of System V strtod(3) library routine.
- X * Does no overflow/underflow checking.
- X *
- X * A real number is defined to be
- X * optional leading white space
- X * optional sign
- X * string of digits with optional decimal point
- X * optional 'e' or 'E'
- X * followed by optional sign or space
- X * followed by an integer
- X *
- X * if ptr is not NULL a pointer to the character terminating the
- X * scan is returned in *ptr. If no number formed, *ptr is set to str
- X * and 0 is returned.
- X *
- X * For speed, we don't do the conversion ourselves. Instead, we find
- X * the end of the number and then call atof() to do the dirty work.
- X * This bought us a 10% speedup on a sample program at uunet.uu.net.
- X */
- X
- X#include <ctype.h>
- X
- Xextern double atof();
- X
- Xdouble
- Xstrtod (s, ptr)
- Xregister char *s, **ptr;
- X{
- X double ret = 0.0;
- X char *start = s;
- X char *begin = NULL;
- X int success = 0;
- X
- X /* optional white space */
- X while (isspace(*s))
- X s++;
- X
- X /* optional sign */
- X if (*s == '+' || *s == '-') {
- X s++;
- X if (*(s-1) == '-')
- X begin = s - 1;
- X else
- X begin = s;
- X }
- X
- X /* string of digits with optional decimal point */
- X if (isdigit(*s) && ! begin)
- X begin = s;
- X
- X while (isdigit(*s)) {
- X s++;
- X success++;
- X }
- X
- X if (*s == '.') {
- X if (! begin)
- X begin = s;
- X s++;
- X while (isdigit(*s))
- X s++;
- X success++;
- X }
- X
- X if (s == start || success == 0) /* nothing there */
- X goto out;
- X
- X /*
- X * optional 'e' or 'E'
- X * followed by optional sign or space
- X * followed by an integer
- X */
- X
- X if (*s == 'e' || *s == 'E') {
- X s++;
- X
- X /* XXX - atof probably doesn't allow spaces here */
- X while (isspace(*s))
- X s++;
- X
- X if (*s == '+' || *s == '-')
- X s++;
- X
- X while (isdigit(*s))
- X s++;
- X }
- X
- X /* go for it */
- X ret = atof(begin);
- X
- Xout:
- X if (! success)
- X s = start; /* in case all we did was skip whitespace */
- X
- X if (ptr)
- X *ptr = s;
- X
- X return ret;
- X}
- X
- X#ifdef TEST
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X double d;
- X char *p;
- X
- X for (argc--, argv++; argc; argc--, argv++) {
- X d = strtod (*argv, & p);
- X printf ("%lf [%s]\n", d, p);
- X }
- X}
- X#endif
- END_OF_FILE
- if test 2023 -ne `wc -c <'./missing.d/strtod.c'`; then
- echo shar: \"'./missing.d/strtod.c'\" unpacked with wrong size!
- fi
- # end of './missing.d/strtod.c'
- fi
- echo shar: End of archive 3 \(of 16\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-